package com.ruoyi.common.swagger.config.plugin;

import io.swagger.annotations.Api;
import io.swagger.annotations.ApiImplicitParam;
import io.swagger.annotations.ApiImplicitParams;
import org.springframework.beans.BeansException;
import org.springframework.beans.factory.config.BeanPostProcessor;
import org.springframework.stereotype.Component;
import org.springframework.util.StringUtils;

import java.lang.annotation.Annotation;
import java.lang.reflect.Field;
import java.lang.reflect.InvocationHandler;
import java.lang.reflect.Method;
import java.lang.reflect.Proxy;
import java.util.Map;

/**
 * @author liyang
 * @description
 * @date 2022-11-15 17:18:25
 */
@Component
public class YouYaApiImplicitParamsBean implements BeanPostProcessor {
    @Override
    public Object postProcessBeforeInitialization(Object bean, String beanName) throws BeansException {
        Class<?> aClass = bean.getClass();
        if (aClass.isAnnotationPresent(Api.class)) {
            Method[] declaredMethods = aClass.getDeclaredMethods();
            for (Method declaredMethod : declaredMethods) {
                Annotation[] annotations = declaredMethod.getAnnotations();
                for (Annotation annotation : annotations) {
                    if (annotation instanceof ApiImplicitParams) {
                        InvocationHandler invocationHandler = Proxy.getInvocationHandler(annotation);
                        try {
                            Field memberValues = invocationHandler.getClass().getDeclaredField("memberValues");
                            memberValues.setAccessible(true);
                            Map o = (Map) memberValues.get(invocationHandler);
                            ApiImplicitParam[] apiImplicitParams = (ApiImplicitParam[]) o.get("value");
                            for (ApiImplicitParam apiImplicitParam : apiImplicitParams) {
                                if (StringUtils.isEmpty(apiImplicitParam.example())) {
                                    continue;
                                }
                                Class<?> aClass1 = Class.forName(apiImplicitParam.example());
                                Object[] enumConstants = aClass1.getEnumConstants();
                                InvocationHandler invocationHandler1 = Proxy.getInvocationHandler(apiImplicitParam);
                                Field memberValues1 = invocationHandler1.getClass().getDeclaredField("memberValues");
                                memberValues1.setAccessible(true);
                                Map o1 = (Map) memberValues1.get(invocationHandler1);
                                StringBuilder stringBuilder = new StringBuilder();
                                stringBuilder.append(apiImplicitParam.value());
                                stringBuilder.append("枚举(");
                                for (Object enumConstant : enumConstants) {
                                    Method[] declaredMethods1 = aClass1.getDeclaredMethods();
                                    for (Method declaredMethod1 : declaredMethods1) {
                                        String name = declaredMethod1.getName();
                                        if (name.equals("values") || name.equals("valueOf")) {
                                            continue;
                                        }
                                        stringBuilder.append(declaredMethod1.invoke(enumConstant));
                                        stringBuilder.append(":");
                                    }
                                    stringBuilder.delete(stringBuilder.length() - 1, stringBuilder.length());
                                    stringBuilder.append(",");
                                }
                                stringBuilder.delete(stringBuilder.length() - 1, stringBuilder.length());
                                stringBuilder.append(")");
                                o1.put("example", "");
                                o1.put("value", stringBuilder.toString());
                            }
                        } catch (Exception e) {
                            e.printStackTrace();
                        }
                    }
                }
            }
        }
        return bean;
    }
}
